﻿using System;
using System.Data.Entity;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.Security;
using CodeContrib;
using CodeContrib.Web;
using CodeContrib.Web.Mvc;
using CodeContrib.Web.Mvc.Html;
using CodeContrib.Web.Mvc.Routing;
using CodeContrib.Web.Routing;
using CodeContribBlog.Data;
using HibernatingRhinos.Profiler.Appender.EntityFramework;

namespace CodeContribBlog.Web.Mvc
{
	public class MvcApplication : HttpApplication
	{
		public void Application_BeginRequest(object sender, EventArgs e)
		{
			HttpContext.Current.VerifySeoUrl();

			ModifyCurrentCulture();

			using (var blogContext = new BlogContext())
			{
				if (!blogContext.Database.Exists())
				{
					blogContext.Database.CreateIfNotExists();
				}
			}

			if (!File.Exists(HttpContext.Current.Request.PhysicalPath))
			{
				var tenantRoute = TenantRouteTable.Find(Context.Request.Url);

				if (tenantRoute != null)
				{
					HttpContext.Current.Items[TenantRoute.HttpContextKey] = tenantRoute;

					var inboundUrl = tenantRoute.RewriteInbound(Context.Request.Url.OriginalString);

					Context.RewritePath(inboundUrl);
				}
			}
		}

		public void Application_EndRequest(object sender, EventArgs e)
		{
		}

		protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
		{
			if (File.Exists(Request.PhysicalPath))
			{
				return;
			}

			var authenticationCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];

			if (authenticationCookie == null)
			{
				return;
			}

			var authenticationTicket = FormsAuthentication.Decrypt(authenticationCookie.Value);

			//GenericIdentity identity = new GenericIdentity(authenticationTicket.Name);

			try
			{
				using (var blogContext = new BlogContext())
				{
					var user = blogContext.Users.FindByEmailAddress(authenticationTicket.Name);

					if (user == null)
					{
						FormsAuthentication.SignOut();
					}

					Context.Items["__User"] = user;
				}
			}
			catch
			{
				FormsAuthentication.SignOut();
			}
		}

		//protected void Application_Error(object sender, EventArgs e)
		//{
		//	Response.Clear();

		//	Exception exception = Server.GetLastError();
		//	HttpException httpException = exception as HttpException;

		//	string actionName = "InternalServerError";

		//	if (httpException != null)
		//	{
		//		switch (httpException.GetHttpCode())
		//		{
		//			case 404:
		//				actionName = "NotFound";

		//				break;
		//		}
		//	}

		//	RequestContext requestContext = ((MvcHandler)Context.CurrentHandler).RequestContext;
		//	requestContext.RouteData.Values["controller"] = "Error";
		//	requestContext.RouteData.Values["action"] = actionName;

		//	IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
		//	IController controller = factory.CreateController(requestContext, "Error");
		//	controller.Execute(requestContext);
		//}

		protected void Application_Start()
		{
			RouteTable.Routes.IgnoreStaticRoutes();
			AreaRegistration.RegisterAllAreas();
			WebApiConfig.Register(GlobalConfiguration.Configuration);
			RouteConfig.RegisterRoutes(RouteTable.Routes);
			FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
			BundleConfig.RegisterBundles(BundleTable.Bundles);
			AuthConfig.RegisterAuth();

			EntityFrameworkProfiler.Initialize();

			ModelMetadataProviders.Current = new FieldTemplateMetadataProvider();

			// Model binders.
			ModelBinders.Binders.Add(typeof (Paging), new PagingBinder());
			ModelBinders.Binders.Add(typeof (Sorting), new SortingBinder());

			PagingExtensions.VisiblePageCount = 5;

			if (AppConfig.EnableRouteDebugger)
			{
				RouteDebugger.RewriteRoutes(RouteTable.Routes);
			}

			Database.SetInitializer(new BlogInitializer(AppConfig.RootUrl));

			using (var blogContext = new BlogContext())
			{
				foreach (var blog in blogContext.Blogs)
				{
					TenantRouteTable.Add(new TenantRouteInfo(blog.Id, blog.Url, blog.Slug));
				}
			}
		}

		private static void ModifyCurrentCulture()
		{
			var modifiedCulture = CultureInfo.CurrentCulture.Clone() as CultureInfo;

			//modifiedCulture.NumberFormat.CurrencySymbol = string.Empty;

			var numberFormatInfo = modifiedCulture.NumberFormat;

			// All negative values will be enclosed in brackets e.g. ($n) or (n$).
			//switch (numberFormatInfo.CurrencyNegativePattern)
			//{
			//    case 5:
			//    case 6:
			//    case 7:
			//    case 8:
			//    case 10:
			//    case 13:
			//    case 15:
			//        {
			//            numberFormatInfo.CurrencyNegativePattern = 4;

			//            break;
			//        }

			//    case 1:
			//    case 2:
			//    case 3:
			//    case 9:
			//    case 11:
			//    case 12:
			//    case 14:
			//        {
			//            numberFormatInfo.CurrencyNegativePattern = 0;

			//            break;
			//        }
			//}

			if (!numberFormatInfo.HasCurrencySymbol())
			{
				// Remove any spaces in the pattern because we won't be showing the currency symbol.

				switch (numberFormatInfo.CurrencyPositivePattern)
				{
					case 2:
						{
							numberFormatInfo.CurrencyPositivePattern = 0;

							break;
						}
					case 3:
						{
							numberFormatInfo.CurrencyPositivePattern = 1;

							break;
						}
				}
			}

			if (!numberFormatInfo.HasPercentSymbol())
			{
				// Remove any spaces in the pattern because we won't be showing the percent symbol.

				switch (numberFormatInfo.PercentNegativePattern)
				{
					case 0:
						{
							numberFormatInfo.PercentNegativePattern = 1;

							break;
						}
					case 7:
						{
							numberFormatInfo.PercentNegativePattern = 2;

							break;
						}
					case 9:
						{
							numberFormatInfo.PercentNegativePattern = 4;

							break;
						}
					case 10:
						{
							numberFormatInfo.PercentNegativePattern = 3;

							break;
						}
					case 11:
						{
							numberFormatInfo.PercentNegativePattern = 5;

							break;
						}
				}

				switch (numberFormatInfo.PercentPositivePattern)
				{
					case 0:
						{
							numberFormatInfo.PercentPositivePattern = 1;

							break;
						}
					case 3:
						{
							numberFormatInfo.PercentPositivePattern = 2;

							break;
						}
				}
			}

			Thread.CurrentThread.CurrentUICulture = modifiedCulture;
			Thread.CurrentThread.CurrentCulture = modifiedCulture;
		}

		public static void RegisterGlobalFilters(GlobalFilterCollection filters)
		{
			filters.Add(new HandleErrorAttribute());
		}
	}
}